package com.samsung.spen.sshare.main.sms;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

import android.app.AlertDialog;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.ContentUris;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.database.Cursor;
import android.graphics.BitmapFactory;
import android.graphics.Typeface;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.provider.ContactsContract.Contacts;
import android.support.v4.app.Fragment;
import android.support.v4.app.NotificationCompat;
import android.support.v4.app.NotificationCompat.Builder;
import android.telephony.SmsMessage;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.samsung.spen.sshare.R;
import com.samsung.spen.sshare.explorer.choosefiles.FilesChooseActivity;
import com.samsung.spen.sshare.main.MainActivity;
import com.samsung.spen.sshare.main.data.RequestSMS;
import com.samsung.spen.sshare.main.data.SshareDataService;
import com.samsung.spen.sshare.networking.connection.NetworkAddress;
import com.samsung.spen.sshare.networking.connection.RequestListAdapter;
import com.samsung.spen.sshare.networking.networkservice.SendReceiveService;
import com.samsung.spen.sshare.networking.sendreceivefile.SendReceiveActivity;

public class RequestSMSListFragment extends Fragment implements
		OnItemClickListener {
	private int mNum;
	private ListView mListView = null;
	private MainActivity bindedActivity = null;
	private View view = null;
	private ArrayList<RequestSMS> mRequests = new ArrayList<RequestSMS>();
	private ArrayList<View> actualViews = new ArrayList<View>();
	private ProgressBar mPBLoading = null;
	private Menu menu;
	private SMSComeReceiver receiver = new SMSComeReceiver();
	private RequestDataAdapter mDataAdapter;
	private RequestSMS choosingSMS = null;

	// Havan
	public static final String IP = SendReceiveService.IP;
	public static final String PORT = SendReceiveService.PORT;

	public static final int MSG_ADD_ITEM = 1;
	public static final int MSG_DELETE_ITEM = 2;

	private static ArrayList<NetworkAddress> listItem;
	private static RequestListAdapter adapter;
	private ListView mConnectionListView;

	private static final String TAG = "CONNECTIONLISTACTIVITY";
	// Havan -- end

	private SshareDataService mSshareDataService;
	private ServiceConnection mServiceConnection = new ServiceConnection() {

		@Override
		public void onServiceDisconnected(ComponentName name) {
			if (name.getClassName().equals(SshareDataService.class.getName())) {
				mSshareDataService = null;
				Toast.makeText(bindedActivity,
						"service disconnected" + name.getShortClassName(),
						Toast.LENGTH_SHORT).show();
			}

			if (name.getClassName().equals(SendReceiveService.class.getName())) {
				bindedActivity.mSendReceiveService = null;
				Toast.makeText(bindedActivity,
						"service disconnected" + name.getShortClassName(),
						Toast.LENGTH_SHORT).show();
			}
		}

		@Override
		public void onServiceConnected(ComponentName name, IBinder service) {
			if (name.getClassName().equals(SshareDataService.class.getName())) {
				mSshareDataService = ((SshareDataService.SshareDataServiceBinder) service)
						.getService();
				Toast.makeText(bindedActivity,
						"service connected: " + name.getShortClassName(),
						Toast.LENGTH_SHORT).show();
				Log.v(this.getClass().toString(), name.getClassName());
				// use service here
//				 for(int i = 0; i<100; i++){
//				 mSshareDataService.insertSMS("0987654321",
//				 System.currentTimeMillis(), "bonjour", "192.168.1.101",
//				 55555);
//				 }

				upgradeRefreshListView();
			}

			if (name.getClassName().equals(SendReceiveService.class.getName())) {
				bindedActivity.mSendReceiveService = ((SendReceiveService.LocalBinder) service)
						.getService();
				Toast.makeText(bindedActivity,
						"service connected: " + name.getShortClassName(),
						Toast.LENGTH_SHORT).show();
				Log.v(this.getClass().toString(), name.getClassName());
				// use service here
				if (choosingSMS != null) {
					startServer();
				} else {
					Toast.makeText(bindedActivity, "No SMS is choosed",
							Toast.LENGTH_SHORT).show();
				}
			}
		}
	};

	// ---Havan--------------
	public static Handler updateConnectionListHandler = new Handler() {

		@Override
		public void handleMessage(Message msg) {
			Log.d(TAG, "MESSAGE TYPE: " + msg.what);
			switch (msg.what) {
			case MSG_ADD_ITEM:
				Log.d(TAG, "MESSAGE TYPE: MSG_ADD_ITEM");
				Bundle receivedData = msg.getData();
				String ipAddr = receivedData.getString("IP");
				Log.d(TAG, "from IP = " + ipAddr);
				int port = receivedData.getInt("PORT");
				Log.d(TAG, "from Port = " + port);
				// for (int i = 0; i < listItem.size(); i++) {
				// NetworkAddress item = listItem.get(i);
				// if (item.getmIp().equals(ipAddr)) {
				// item.setMport(port);
				// item.setmStatus(NetworkAddress.CONNECTED);
				// adapter.remove(item);
				// listItem.add(i, item);
				// break;
				// }
				// if (i == (listItem.size() - 1))
				adapter.add(new NetworkAddress(ipAddr, port,
						NetworkAddress.CONNECTED));
				// }

				break;
			case MSG_DELETE_ITEM:
				Log.d(TAG, "MESSAGE TYPE: MSG_DELETE_ITEM");
				String ip = msg.getData().getString("IP");
				for (int i = 0; i < listItem.size(); i++) {
					NetworkAddress item = listItem.get(i);
					if (item.getmIp().equals(ip))
						adapter.remove(item);
				}

				break;
			default:
				Log.d(TAG, "MESSAGE TYPE:UNKNOWN --" + msg.what);
				break;
			}

			super.handleMessage(msg);
		}

	};

	// Havan -----end
	public RequestSMSListFragment newInstance(int num) {
		RequestSMSListFragment f = new RequestSMSListFragment();

		Bundle args = new Bundle();
		args.putInt("num", num);
		f.setArguments(args);

		return f;
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		mNum = getArguments() != null ? getArguments().getInt("num") : 1;
		this.bindedActivity = (MainActivity) this.getActivity();
		setHasOptionsMenu(true);

		bindedActivity.bindService(new Intent(bindedActivity,
				SshareDataService.class), mServiceConnection,
				Context.BIND_AUTO_CREATE);
		// mDataAdapter = new RequestDataAdapter(this.bindedActivity);
		Log.v(this.getClass().toString(), "oncreate requestsmsListFragment");
	}

	@Override
	public void onResume() {
		super.onResume();
		IntentFilter filter = new IntentFilter(
				"android.provider.Telephony.SMS_RECEIVED");
		filter.setPriority(Integer.MAX_VALUE);
		bindedActivity.registerReceiver(receiver, filter);
	}

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {
		Log.v("Fragment", "requestsms oncreateView");
		View v = inflater.inflate(R.layout.main_activity_sms_requests,
				container, false);
		this.view = v;
		return v;
	}

	@Override
	public void onActivityCreated(Bundle bundle) {
		super.onActivityCreated(bundle);
		mListView = (ListView) view.findViewById(R.id.lv_requests);
		mListView.setOnItemClickListener(this);
		mListView.setAdapter(mDataAdapter);
		

		mPBLoading = (ProgressBar) view.findViewById(R.id.pb_requests_loading);

		// Havan
		listItem = new ArrayList<NetworkAddress>();
		adapter = new RequestListAdapter(bindedActivity,
				R.layout.network_connection_row, listItem);

		mConnectionListView = (ListView) view
				.findViewById(R.id.lv_connectting_list);
		mConnectionListView.setAdapter(adapter);

		// Havan -- end
		Log.v(this.getClass().toString(),
				"onactivitycreate requestsmsListFragment");
	}

	@Override
	public void onStop() {
		super.onDestroy();
		bindedActivity.unregisterReceiver(receiver);
		super.onStop();
	}

	@Override
	public void onDestroy() {
		if (mServiceConnection != null
				|| bindedActivity.mSendReceiveService != null) {
			bindedActivity.unbindService(mServiceConnection);
		}
		super.onDestroy();
	}

	@Override
	public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
		inflater.inflate(R.menu.main_fragment_requestsms, menu);
		this.menu = menu;
		super.onCreateOptionsMenu(menu, inflater);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.menu_select_all:
			for (RequestSMS requestSMS : mRequests) {
				requestSMS.setChecked(true);
			}
			for (View view : actualViews) {
				((CheckBox) view.findViewById(R.id.cb_request))
						.setChecked(true);
			}
			item.setVisible(false);
			this.menu.getItem(2).setVisible(true);
			break;
		case R.id.menu_deselect_all:
			for (RequestSMS requestSMS : mRequests) {
				requestSMS.setChecked(false);
			}
			for (View view : actualViews) {
				((CheckBox) view.findViewById(R.id.cb_request))
						.setChecked(false);
			}
			item.setVisible(false);
			this.menu.getItem(1).setVisible(true);
			break;
		case R.id.menu_delete_selected:
			ArrayList<Integer> positions = new ArrayList<Integer>();
			int length = mRequests.size();
			for (int i = length - 1; i >= 0; i--) {
				RequestSMS requestSMS = mRequests.get(i);
				if (requestSMS.isChecked()) {
					mSshareDataService.deleteRequestSMS(requestSMS.getId());
					mRequests.remove(i);
					mDataAdapter.remove(requestSMS);
					positions.add(i);
				}
			}
			break;
		default:
			break;
		}
		return super.onOptionsItemSelected(item);
	}

	public void refreshListView() {
		RequestSMS sms = mRequests.get(0);
		mDataAdapter.remove(sms);
		mDataAdapter.insert(sms, 0);
	}

	public void upgradeRefreshListView() {
		UpdateTask updateTask = new UpdateTask();
		updateTask.execute(new Void[1]);
	}

	class UpdateTask extends
			AsyncTask<Void, ArrayList<RequestSMS>, ArrayList<RequestSMS>> {

		@Override
		protected ArrayList<RequestSMS> doInBackground(Void... params) {
			// Log.v(RequestSMSListFragment.class.toString(),
			// "list size: " + mSshareDataService.getRequestSMSListPartially(50,
			// 0).size());
			// ArrayList<RequestSMS> arr = new ArrayList<RequestSMS>();
			// int count = 0;
			// do{
			// arr = mSshareDataService.getRequestSMSListPartially(50, count);
			// count += 50;
			// if(arr != null){
			// mRequests.addAll(arr);
			// }
			// } while (arr != null && arr.size() > 0);
			mRequests = mSshareDataService.getRequestSMSList();
			return mRequests;
		}

		@Override
		protected void onPostExecute(ArrayList<RequestSMS> result) {
			mDataAdapter = new RequestDataAdapter(bindedActivity);
			mListView.setAdapter(mDataAdapter);
			if(mPBLoading.getVisibility() == View.VISIBLE){
				mPBLoading.setVisibility(View.GONE);
			}
		}

	}

	class RequestDataAdapter extends ArrayAdapter<RequestSMS> {
		public RequestDataAdapter(Context ctx) {
			super(ctx, R.layout.main_listview_request_item, mRequests);
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			View row = convertView;
			DataHolder holder;
			if (row == null) {
				LayoutInflater inflater = bindedActivity.getLayoutInflater();
				row = inflater.inflate(R.layout.main_listview_request_item,
						parent, false);
				holder = new DataHolder(row);
				row.setTag(holder);
				actualViews.add(row);
			} else {
				holder = (DataHolder) row.getTag();
			}
			holder.setData(mRequests.get(position), position);
			return row;
		}
	}

	class DataHolder {
		ImageView ivConnectionState;
		TextView tvContact, tvPhone, tvDateTime;
		CheckBox cb;
		int position;

		public DataHolder(View view) {
			ivConnectionState = (ImageView) view
					.findViewById(R.id.iv_connection_state);
			tvContact = (TextView) view.findViewById(R.id.tv_contact);
			tvPhone = (TextView) view.findViewById(R.id.tv_phone);
			tvDateTime = (TextView) view.findViewById(R.id.tv_date_time);
			cb = (CheckBox) view.findViewById(R.id.cb_request);
			cb.setOnClickListener(new OnClickListener() {

				@Override
				public void onClick(View v) {
					mRequests.get(position).setChecked(cb.isChecked());
					// Log.v(RequestSMSListFragment.class.toString(),
					// position+":"+ cb.isChecked());
				}
			});
			
		}

		public void setData(RequestSMS request, int pos) {
			this.position = pos;
			String name = "No contact";
			if (request.getStatus() == Constants.SMS_UNREAD) {
				tvContact.setTypeface(null, Typeface.BOLD_ITALIC);
			} else if (request.getStatus() == Constants.SMS_READ) {
				tvContact.setTypeface(null, Typeface.NORMAL);
			}
			tvContact.setText(request.getContactName());
			tvPhone.setText(request.getPhoneNumber());
			// tvDateTime.setText((new Date(request.getDateTime())).toString());
			tvDateTime.setText(bindedActivity.getTimeString(request
					.getDateTime()));
			cb.setChecked(request.isChecked());
			// Log.v(RequestSMSListFragment.class.toString(),
			// request.isChecked()+"");
			ivConnectionState.setImageBitmap(
					BitmapFactory.decodeStream(openPhoto(request.getContactID())));
			//ivConnectionState.setImageResource(R.drawable.ic_launcher);
			Toast.makeText(bindedActivity, request.getId()+"", Toast.LENGTH_SHORT).show();
		}
	}
	
	public InputStream openPhoto(long contactId) {
	     Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, contactId);
	     Uri photoUri = Uri.withAppendedPath(contactUri, Contacts.Photo.CONTENT_DIRECTORY);
	     Cursor cursor = bindedActivity.getContentResolver().query(photoUri,
	          new String[] {Contacts.Photo.PHOTO}, null, null, null);
	     if (cursor == null) {
	         return null;
	     }
	     try {
	         if (cursor.moveToFirst()) {
	             byte[] data = cursor.getBlob(0);
	             if (data != null) {
	                 return new ByteArrayInputStream(data);
	             }
	         }
	     } finally {
	         cursor.close();
	     }
	     return null;
	 } 

	class SMSComeReceiver extends BroadcastReceiver implements Constants {
		private static final String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";

		@Override
		public void onReceive(Context context, Intent intent) {
			if (intent.getAction().equals(SMS_RECEIVED)) {
				Bundle bundle = intent.getExtras();
				Log.d(this.getClass().toString(), "SMS received");
				Toast.makeText(context, "sms received", Toast.LENGTH_SHORT)
						.show();
				Object[] pdus = (Object[]) bundle.get("pdus");
				SmsMessage[] messages = new SmsMessage[pdus.length];
				for (int i = 0; i < pdus.length; i++) {
					messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
				}

				String body = "";
				String phoneNum = "";
				long time = 0;
				String ip;
				int port;
				String content = "";

				SmsMessage sms = messages[0];
				phoneNum = messages[0].getDisplayOriginatingAddress();
				time = messages[0].getTimestampMillis();
				try {
					if (messages.length == 1 || sms.isReplace()) {
						body = sms.getDisplayMessageBody();
					} else {
						StringBuilder bodyText = new StringBuilder();
						for (int i = 0; i < messages.length; i++) {
							bodyText.append(messages[i].getMessageBody());
						}
						body = bodyText.toString();
					}
					if (body.contains(TOKEN_SEPARATED)) {
						String[] tokens = body.split(TOKEN_SEPARATED);
						if (tokens[0].equals(INDENTIFICATION_STRING)) {
							this.abortBroadcast();
							// Handle sms
							ip = tokens[1];
							port = Integer.parseInt(tokens[2]);
							if (tokens.length == 4) {
								content = tokens[3];
							}
							long id = mSshareDataService.insertSMS(phoneNum,
									time, content, ip, port);
							RequestSMS rs = new RequestSMS(id, phoneNum, time,
									content, ip, port, Constants.SMS_UNREAD);
							Log.d(RequestSMSListFragment.class.toString(), "Port when sms receive : " + port);
							// fire notification
							NotificationCompat.Builder builder = new Builder(
									bindedActivity);
							builder.setSmallIcon(R.drawable.ic_launcher);
							builder.setContentTitle("Request From : "
									+ phoneNum);
							builder.setContentText(content);
							NotificationManager mNotificationManager = (NotificationManager) bindedActivity
									.getSystemService(Context.NOTIFICATION_SERVICE);
							Notification notification = builder.build();

							Intent intentNtf = new Intent(bindedActivity,
									MainActivity.class);
							intentNtf.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
							PendingIntent pi = PendingIntent.getActivity(
									bindedActivity, 0, intentNtf, 0);
							notification.contentIntent = pi;
							notification.flags |= Notification.FLAG_AUTO_CANCEL
									| Notification.FLAG_SHOW_LIGHTS;

							mNotificationManager.notify(
									(int) System.currentTimeMillis(),
									notification);

							// upgradRefreshListView();
							// refreshListView();
							rs.setContactName(bindedActivity
									.getNameFromPhone(rs.getPhoneNumber()));
							mRequests.add(0, rs);
							mDataAdapter.insert(rs, 0);
							mDataAdapter.remove(rs);
							Log.v(RequestSMSListFragment.class.toString(),
									"receive SMS in SMSListFragment");
						}
					}

					Log.d("SMS Body", body);
				} catch (Exception e) {

				}
			}
		}

	}

	@Override
	public void onItemClick(AdapterView<?> parent, View view, int position,
			long id) {
		if (parent.getId() == R.id.lv_requests) {
			// Toast.makeText(bindedActivity, "click",
			// Toast.LENGTH_SHORT).show();
			AlertDialog.Builder builder = new AlertDialog.Builder(
					bindedActivity);
			RequestSMS sms = mRequests.get(position);
			choosingSMS = sms;
			builder.setTitle(sms.getContactName() + "-" + sms.getPhoneNumber());
			builder.setMessage(sms.getContent());
			builder.setCancelable(true);
			builder.setPositiveButton("Send Files",
					new DialogInterface.OnClickListener() {
						@Override
						public void onClick(DialogInterface dialog, int which) {
							if (bindedActivity.mSendReceiveService == null) {
								bindedActivity.bindService(new Intent(
										bindedActivity,
										SendReceiveService.class),
										mServiceConnection,
										Context.BIND_AUTO_CREATE);
							} else {
								startServer();
							}

							// choose files
							Intent intent = new Intent(bindedActivity,
									SendReceiveActivity.class);
							intent.putExtra(SendReceiveService.IP,
									choosingSMS.getIp());
							intent.putExtra(SendReceiveService.PORT,
									choosingSMS.getPort()+"");
							Log.d(RequestSMSListFragment.class.toString(), "IP : " + choosingSMS.getIp());
							Log.d(RequestSMSListFragment.class.toString(), "Port : " + choosingSMS.getPort());
							startActivity(intent);
						}
					});
			builder.setNegativeButton("Cancel",
					new DialogInterface.OnClickListener() {
						@Override
						public void onClick(DialogInterface dialog, int which) {

						}
					});
			builder.create().show();
			int result = mSshareDataService.updateSMSStatus(Constants.SMS_READ,
					sms.getId());
			if (result == 1) {
				sms.setStatus(Constants.SMS_READ);
				TextView tvContact = (TextView) view
						.findViewById(R.id.tv_contact);
				if (sms.getStatus() == Constants.SMS_UNREAD) {
					tvContact.setTypeface(null, Typeface.BOLD_ITALIC);
				} else if (sms.getStatus() == Constants.SMS_READ) {
					tvContact.setTypeface(null, Typeface.NORMAL);
				}
				// refreshListView();
			}
			
			//insert in connecting list
		}

	}

	public void startServer() {
		Map<String, String> map = new HashMap<String, String>();
		map.put(SendReceiveService.IP, choosingSMS.getIp());
		map.put(SendReceiveService.PORT, choosingSMS.getPort() + "");
		// call Miss Van's service
		bindedActivity.mSendReceiveService.startServer(
				SendReceiveService.REQUEST_REPLY_SMS, map);
	}
}
